package cn.yhbk.web.modules.manager.Service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.hash.Hash;
import cn.yhbk.web.common.exception.ApiException;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaDetails.AddDetails;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaDetails.DetailsResP;
import cn.yhbk.web.modules.manager.Pojo.Entity.GpaCheckDetails;
import cn.yhbk.web.modules.manager.Mapper.GpaCheckDetailsMapper;
import cn.yhbk.web.modules.manager.Pojo.Entity.TbGpaDetailsResource;
import cn.yhbk.web.modules.manager.Pojo.VO.Details.UpdateDetail;
import cn.yhbk.web.modules.manager.Pojo.VO.Resource.ResourceResp;
import cn.yhbk.web.modules.manager.Service.IGpaCheckDetailsService;
import cn.yhbk.web.modules.manager.Service.ITbGpaCheckService;
import cn.yhbk.web.modules.manager.Service.ITbGpaDetailsResourceService;
import cn.yhbk.web.modules.manager.Service.ITbStudentService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 有何不可
 * @since 2023-09-10
 */
@Service
@Slf4j
public class GpaCheckDetailsServiceImpl extends ServiceImpl<GpaCheckDetailsMapper, GpaCheckDetails> implements IGpaCheckDetailsService {


    @Autowired
    GpaCheckDetailsMapper detailsMapper;

    @Autowired
    ITbGpaDetailsResourceService resourceService;

    @Autowired
    ITbGpaDetailsResourceService checkResourceService;

    @Autowired
    ITbStudentService studentService;

    @Lazy
    @Autowired
    ITbGpaCheckService checkService;

    @Override
    @Transactional
    public boolean addDetails(Map<Long, List<AddDetails>> details, Long checkId) {

        List<TbGpaDetailsResource> resList = new ArrayList<>();

        Set<Long> keySet = details.keySet();
        for (Long key : keySet) {
            List<AddDetails> addDetails = details.get(key);
            if (Objects.isNull(addDetails)) continue;

            for (AddDetails item : addDetails) {
                if (Objects.isNull(item.getResource()) || item.getResource().isEmpty())
                    throw new ApiException("证明材料不能为空");
                GpaCheckDetails detail = new GpaCheckDetails();
                detail.setCheckId(checkId);
                detail.setCategoryId(key);
                detail.setGpaNum(item.getGpaNum());
                detail.setActivityName(item.getActivityName());

                //保存该详情
                boolean save = save(detail);
                if (!save) {
                    log.error("保存detail失败!");
                    throw new ApiException("保存失败!请联系管理员");
                }
                Long detailId = detail.getId();

                //处理附件
                List<String> resource = item.getResource();
                List<TbGpaDetailsResource> resListTmp = resource.stream().map(pathName -> {
                    TbGpaDetailsResource tbGpaDetailsResource = new TbGpaDetailsResource();
                    tbGpaDetailsResource.setPath(pathName);
                    tbGpaDetailsResource.setGpaDetailId(detailId);
                    return tbGpaDetailsResource;
                }).collect(Collectors.toList());

                resList.addAll(resListTmp);
            }
        }

        //保存附件
        boolean saveBatchRes = resourceService.saveBatch(resList);
        if (!saveBatchRes) {
            log.error("保存resource失败!");
            throw new ApiException("保存失败!请联系管理员");
        }
        return true;
    }

    @Override
    public List<DetailsResP> getDetailsByCheckIds(List<Long> checkIds) {
        if (Objects.isNull(checkIds) || checkIds.isEmpty()) return new ArrayList<>();
        QueryWrapper<GpaCheckDetails> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<GpaCheckDetails> lambda = wrapper.lambda();

        lambda.in(GpaCheckDetails::getCheckId, checkIds);
        lambda.orderByAsc(GpaCheckDetails::getCode);

        List<GpaCheckDetails> details = list(lambda);

        List<Long> detailIds = details.stream().map(GpaCheckDetails::getId).collect(Collectors.toList());

        //处理外链
        List<TbGpaDetailsResource> resource = resourceService.getResourceByDetailsId(detailIds);

        List<ResourceResp> resourceRes = checkResourceService.getPath(resource);

        Map<Long, List<ResourceResp>> resourceMap = resourceRes.stream().collect(Collectors.groupingBy(ResourceResp::getGpaDetailId));
        log.debug("resourceMap:{}", resourceMap);
        List<DetailsResP> resList = details.stream().map(item -> {
            DetailsResP resP = new DetailsResP();
            BeanUtil.copyProperties(item, resP);
            List<ResourceResp> resourceList = resourceMap.get(item.getId());
            List<Map<String, String>> resourcePath;
            if (Objects.isNull(resourceList)) {
                resourcePath = new ArrayList<>();
            } else {
                resourcePath = resourceList.stream().map(resourceResp -> {
                    Map<String, String> tmpMap = new HashMap<>();
                    tmpMap.put("newFileName", resourceResp.getPath());
                    tmpMap.put("url", resourceResp.getUrl());
                    return tmpMap;
                }).collect(Collectors.toList());
            }

            resP.setResource(resourcePath);
            return resP;
        }).collect(Collectors.toList());
        return resList;
    }

    @Override
    public boolean delDetailByCheckId(Long checkId) {

        //拿到该申请记录的所有详情id
        List<Long> detailsId = detailsMapper.getDetailsIdByCheckId(checkId);
        if (detailsId.isEmpty()) return true;

        //删除附件

        boolean resourceSuc = resourceService.delResourceByDetailsId(detailsId);
        if (!resourceSuc) return false;

        return removeBatchByIds(detailsId);
    }

    @Override
    public boolean pass(Long detailId) {
        return updateHasCheck(detailId, true, "");

    }

    @Override
    public boolean refuse(Long detailId, String refuseReason) {

        return updateHasCheck(detailId, false, refuseReason);
    }

    @Override
    @Transactional
    public boolean updateDetail(Long detailId, UpdateDetail updateDetail) {
        if (Objects.isNull(detailId)) return false;

        boolean judgeCode = checkDetailCode(detailId);
        if (!judgeCode) throw new ApiException("该详情已通过，不能再修改");

        UpdateWrapper<GpaCheckDetails> wrapper = new UpdateWrapper<>();
        LambdaUpdateWrapper<GpaCheckDetails> lambda = wrapper.lambda();

        lambda.eq(GpaCheckDetails::getId, detailId);

        lambda.set(!Objects.isNull(updateDetail.getCategoryId()), GpaCheckDetails::getCategoryId, updateDetail.getCategoryId());
        lambda.set(!Strings.isBlank(updateDetail.getActivityName()), GpaCheckDetails::getActivityName, updateDetail.getActivityName());
        lambda.set(!Objects.isNull(updateDetail.getGpaNum()), GpaCheckDetails::getGpaNum, updateDetail.getGpaNum());
        lambda.set(GpaCheckDetails::getRefuseReason, null);

        boolean update = update(lambda);
        if (!update) return false;

        if (updateDetail.getPath().isEmpty()) return true;
        boolean updateResource = resourceService.updateFile(detailId, updateDetail.getPath());
        if (!updateResource) throw new ApiException("更新失败!");

        return true;
    }

    @Override
    public boolean judgeDetailIdStu(Long adminId, Long detailId) {
        Long stuId = studentService.getStudentIdByAdminId(adminId);
        List<Long> checkIds = checkService.getCheckIdsByStuId(stuId);
        if (checkIds.isEmpty()) return false;

        QueryWrapper<GpaCheckDetails> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<GpaCheckDetails> lambda = wrapper.lambda();

        lambda.eq(GpaCheckDetails::getId, detailId);
        lambda.in(GpaCheckDetails::getCheckId, checkIds);

        List<GpaCheckDetails> list = list(lambda);
        return !list.isEmpty();
    }

    private boolean checkDetailCode(Long detailId) {
        GpaCheckDetails byId = getById(detailId);
        if (Objects.isNull(byId)) return false;
        return byId.getCode() != 1;
    }

    private boolean updateHasCheck(Long detailId, boolean res, String refuseReason) {
        UpdateWrapper<GpaCheckDetails> wrapper = new UpdateWrapper<>();
        LambdaUpdateWrapper<GpaCheckDetails> lambda = wrapper.lambda();

        lambda.eq(GpaCheckDetails::getId, detailId);

        if (res) lambda.set(GpaCheckDetails::getCode, 1);
        else lambda.set(GpaCheckDetails::getCode, 2);

        lambda.set(GpaCheckDetails::getHasCheck, res);
        lambda.set(!Strings.isBlank(refuseReason), GpaCheckDetails::getRefuseReason, refuseReason);

        return update(lambda);

    }
}
